<template>
  <div class="code-editor" :class="currentTheme" :style="{height:height}">
    <div class="toolbar" v-show="toolbarShow">
      <el-select popper-class="tool" class="tool" size="mini" style="width: 120px" v-model="currentTheme"
                 @change="onChangeTheme" placeholder="主题选择">
        <el-option
          v-for="item in themeList"
          :key="item.value"
          :label="item"
          :value="item">
        </el-option>
      </el-select>
      <el-select class="tool" size="mini" style="width: 120px" v-model="currentLanguage" @change="onChangeLanguage"
                 placeholder="语言选择">
        <el-option
          v-for="item in languageList"
          :key="item.value"
          :label="item"
          :value="item">
        </el-option>
      </el-select>
      <el-button-group class="tool">
        <el-button size="mini">运行代码</el-button>
        <el-button size="mini">格式化</el-button>
        <el-button size="mini">清除</el-button>
      </el-button-group>
    </div>
    <div id="code-box">
      <!--<codemirror style="height: 100%"-->
      <!--ref="mycode":value=""-->
      <!--v-model="codeText"-->
      <!--:options="options"-->
      <!--class="code"-->
      <!--&gt;</codemirror>-->
      <textarea ref="mycode" class="code" v-model="codeText"></textarea>
    </div>
  </div>
</template>

<script>
  import CodeMirror from 'codemirror/lib/codemirror'
  import 'codemirror/mode/javascript/javascript.js'
  import 'codemirror/mode/groovy/groovy.js'
  import 'codemirror/addon/lint/json-lint.js'
  import 'codemirror/mode/python/python.js'
  import 'codemirror/addon/hint/show-hint.css'
  import 'codemirror/addon/hint/show-hint.js'
  import 'codemirror/addon/hint/anyword-hint.js'
  // 核心样式
  import 'codemirror/lib/codemirror.css'
  // 引入主题后还需要在 options 中指定主题才会生效
  import 'codemirror/theme/rubyblue.css'
  import 'codemirror/theme/darcula.css'
  import 'codemirror/theme/yonce.css'
  import 'codemirror/addon/lint/lint'
  import 'codemirror/addon/lint/lint.css'
  import 'codemirror/addon/lint/json-lint'
  import 'codemirror/mode/clike/clike'
  import 'codemirror/keymap/sublime'
  import 'codemirror/addon/display/autorefresh'
  import '../../css/solarized-dark.css'
  import '../../css/idea-black.css'
  import '../../css/solarized-light.css'

  //及时自动更新，配置里面也需要设置autoRefresh为true
  //代码补全提示
  import 'codemirror/addon/hint/anyword-hint.js'
  import 'codemirror/addon/hint/css-hint.js'
  import 'codemirror/addon/hint/html-hint.js'
  import 'codemirror/addon/hint/javascript-hint.js'
  import 'codemirror/addon/hint/show-hint.css'
  import 'codemirror/addon/hint/show-hint.js'
  import 'codemirror/addon/hint/sql-hint.js'
  import 'codemirror/addon/hint/xml-hint.js'
  // 折叠
  import 'codemirror/addon/fold/foldgutter.css'
  import 'codemirror/addon/fold/foldcode'
  import 'codemirror/addon/fold/foldgutter'
  import 'codemirror/addon/fold/brace-fold'
  import 'codemirror/addon/fold/comment-fold'

  export default {
    name: 'CodeEditor',
    components: {
      CodeMirror
    },
    data () {
      return {
        codemirror: null,
        themeList: ['rubyblue', 'idea-black', 'solarized-dark', 'solarized-light'],
        languageList: ['javascript', 'application/json', 'groovy'],
      }
    },
    created () {
    },
    mounted () {
      this.initCodeEditor()
      this.initCodeEditorEventBind()
      this.doFormatCode()
      //   this.refresh()
    },

    methods: {
      initCodeEditor () {
        this.codemirror = CodeMirror.fromTextArea(this.$refs.mycode, {
          autofocus: true,
          readOnly: this.readOnly,
          // value: this.codeText,
          autoRefresh: true,
          tabSize: 2, // 缩进格式
          theme: this.currentTheme, // 主题，对应主题库 JS 需要提前引入darcula
          mode: this.currentLanguage,
          lineNumbers: true, // 显示行号
          line: true,
          styleActiveLine: true, // 高亮选中行
          lineWrapping: true,
          keyMap: 'sublime',
          hintOptions: {
            hint: function (editor, keywords, getToken, options) {
              let Pos = CodeMirror.Pos
              let cur = editor.getCursor()
              let token = editor.getTokenAt(cur)
              const end = cur.ch
              const start = end
              console.log(cur)
              return {list: ['frames'], from: Pos(cur.line, start), to: Pos(cur.line, end)}
            },
            completeSingle: false,
            tables: {
              users: ['name', 'score', 'birthDate'],
              countries: ['name', 'population', 'size']
            }
          },
          // extraKeys: {"Ctrl-/": "autocomplete"},
          foldGutter: true,
          lineWrapping: true,
          gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter', 'CodeMirror-lint-markers'],
        })
        this.refresh()
      },
      initCodeEditorEventBind () {
        let _that = this
        this.codemirror.on('change', function () {
          _that.$emit('update:codeText', _that.codemirror.getValue())
        })
        this.codemirror.on('cursorActivity', function () {
          // _that.codemirror.showHint();
        })
        this.codemirror.on('inputRead', function (instance, changeObj) {
          _that.codemirror.showHint()
        })
      },
      onChangeTheme () {
        this.doChangeTheme()
      },
      doChangeTheme () {
        this.codemirror.setOption('theme', this.currentTheme)
      },
      onChangeLanguage () {
        this.doChangeLanguage()
      },
      doChangeLanguage () {
        this.codemirror.setOption('mode', this.currentLanguage)
      },
      refresh () {
        this.codemirror && this.codemirror.refresh()
      },
      setText (data) {
        this.codemirror.setValue(data)
      },
      doFormatCode () {
        try {
          let text = JSON.stringify(JSON.parse(this.codemirror.getValue()), null, 2) + '\n\n\n'
          this.codemirror.setValue(text)
        } catch (e) {
          console.log(e)
        }
      },
      checkValid () {
        setTimeout(() => {
          // this.codemirror.refresh()
          // const container = this.$refs.codeMirror
          // const len = container.querySelectorAll('.CodeMirror-lint-marker-error').length
          // this.isValid = !!len && len > 0
        }, 500)
      },
      getValue () {
        return this.codemirror.getValue()
      }
    },
    watch: {
      codeText (value) {
        // this.codemirror.setValue(value);
      }
    },
    props: {
      readOnly: {
        type: Boolean,
        default: false
      },
      codeText: {
        type: String,
        default: ''
      },
      currentTheme: {
        type: String,
        default: 'rubyblue'
      },
      toolbarShow: {
        type: Boolean,
        default: false
      },
      currentLanguage: {
        type: String,
        default: 'application/json'
      },
      height: {
        type: String,
        default: '800px'
      }
    }
  }
</script>

<style>
  .code-editor {
  }

  #code-box {
    height: 100%;
  }

  .code-editor #code-box .CodeMirror {
    height: 100% !important;
  }

  .code-editor {
    border: 1px solid #f3f3f4;
    background: #f3f3f4;
  }

  . CodeMirror-line {
    line-height: 20px;
    font-size: 20px;
  }
</style>
